`timescale 1ns / 1ns
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/04/30 01:10:56
// Design Name: 
// Module Name: inst_analyze
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module inst_analyze(
	input logic cpu_clk,
	input logic cpu_rst_n,
	input logic [31: 0] pre_inst,
	input logic [31: 0] pre_pc,
	input logic inst_en,//指令是否有效
	input logic [31: 0] ras_addr,
    output logic[1:0] analyze_result,//00代表不是分支，01代表条件跳转，10代表直接直接跳转
    output logic[31:0] analyze_addr,//跳转地址
	output logic branch,
	output logic store,
	output logic ras_we,
	output logic ras_re
	);
    logic [5: 0] op,func;
	logic [31: 0] jump_addr;
	logic [31: 0] signed_imm, branch_addr, analyze_addr_pre;
	logic _reg, j, jal, jr, beq, bne, bgez_before, blez, jalr, branch_inst, bgtz, bgezal, bltzal;
	logic absolute_jump, reg_jump;
	logic ras_re_pre, ras_we_pre;

	assign op = pre_inst[31: 26];
	assign func = pre_inst[5 : 0];
	assign beq =  ~op[5] & ~op[4] & ~op[3] & op[2] & ~op[1] & ~op[0] ;
    assign bne =  ~op[5] & ~op[4] & ~op[3] & op[2] & ~op[1] & op[0] ;
	assign bgez_before = ~op[5] & ~op[4] & ~op[3] & ~op[2] & ~op[1] & op[0];
	assign bgtz = ~op[5] & ~op[4] & ~op[3] & op[2] & op[1] & op[0];
	assign blez = ~op[5] & ~op[4] & ~op[3] & op[2] & op[1] & ~op[0];		
	assign j =  ~op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & ~op[0] ;
    assign jal =  ~op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & op[0] ;
	assign jalr = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & ~func[1] & func[0];
    assign jr = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & ~func[1] & ~func[0];
	assign bgezal = bgez_before & pre_inst[20] & pre_inst[16];
	assign bltzal = bgez_before & pre_inst[20] & ~pre_inst[16];
	assign branch = beq | bne | bgez_before | j | jal | bgtz | blez;


	assign _reg = ~|op;
	assign ras_re = ras_re_pre & inst_en;
	assign ras_we = ras_we_pre & inst_en;
	assign jump_addr = {pre_pc[31: 28], pre_inst[25: 0], 2'b00};
	assign signed_imm = pre_inst[15] == 1'b1 ? {16'hffff, pre_inst[15: 0]} : {16'h0000, pre_inst[15: 0]};
	assign branch_addr = (signed_imm << 2) + pre_pc + 32'b100;
	always_ff @(posedge cpu_clk)begin
		absolute_jump <= j | jal;
		reg_jump <= jr | jalr;
		branch_inst <= beq | bne | bgez_before | bgtz | blez;
		// signed_imm <= pre_inst[15] == 1'b1 ? {16'hffff, pre_inst[15: 0]} : {16'h0000, pre_inst[15: 0]};
		// jump_addr <= {pre_pc[31: 28], pre_inst[25: 0], 2'b00};
		analyze_result[1] <= j | jal | jr | jalr;
		analyze_result[0] <= beq | bne | bgez_before | bgtz | blez | jr | jalr;
		store <= beq | bne | bgez_before | jr | jalr;
		ras_we_pre <= bgezal | bltzal | jal | jalr;
		ras_re_pre <= (jr | jalr) & (pre_inst[25: 21] == 5'd31);
		// branch_addr <= (signed_imm << 2) + pre_pc;
		analyze_addr <= {32{jr | jalr}} & ras_addr | {32{j | jal}} & jump_addr | {32{beq | bne | bgez_before | bgtz | blez}} & branch_addr;
	end
endmodule
